#include "CCopyFileWidget.h"
#include "../Common/CCommonFunction.h"
#include "ui_CCopyFileWidget.h"
#include "../Bridge/CComponentBridge.h"

#include <QDateTime>
#include <QDir>
#include <QDomDocument>
#include <QFileDialog>
#include <QProcess>
#include <QTextStream>
#include <private/qzipreader_p.h>
#include <private/qzipwriter_p.h>

const QString STR_TITLE = "文件拷贝";

const QString FILE_NAME = "CopyFile.xml";
const QString MODEL_NAME = "CopyFile";
const QString COPY_FILE_INFO_TAG = "CopyFileInfo";
const QString UI_COPY_FILE_INFO_TAG = "UICopyFileInfo";
const QString TARGET_PATH_TAG = "TargetPath";
const QString SRC_PATH_TAG = "SrcPath";
const QString PATH_ATRR_TAG = "path";
const QString NAME_TAG = "Name";
const QString CHECKED_ATRR_TAG = "checked";
const QString WATCHER_ATTR_TAG = "watcher";
const QString ZXP_PATH_TAG = "ZXPPath";
const QString CERTIFICATE_PATH_TAG = "CertificatePath";
const QString PASSWORD_TAG = "password";
const QString VERSION_ATTR = "Version";

QString CCopyFileWidget::s_strFileName = QString();

CCopyFileWidget::CCopyFileWidget(QWidget* parent)
    : CMyWindow(parent),
      ui(new Ui::CCopyFileWidget)
{
    ui->setupUi(this);

    this->setWindowTitle(STR_TITLE);

    CCommonFunction::GetDataSavePath(s_strFileName);
    s_strFileName += FILE_NAME;

    // 加载文件
    LoadFile();

    connect(&m_copyFileSystem, SIGNAL(signalFileChanged(const QString&)), this, SLOT(slotCopyFileChanged(const QString&)));
    connect(&m_copyFileSystem, SIGNAL(signalDirectoryChanged(const QString&)), this, SLOT(slotCopyFileDirectoryChanged(const QString&)));

    connect(&m_uiCopyFileSystem, SIGNAL(signalFileChanged(const QString&)), this, SLOT(slotUiCopyFileChanged(const QString&)));
    connect(&m_uiCopyFileSystem, SIGNAL(signalDirectoryChanged(const QString&)), this, SLOT(slotUiCopyFileDirectoryChanged(const QString&)));
}

CCopyFileWidget::~CCopyFileWidget()
{
    SaveFile();

    delete ui;
}

void CCopyFileWidget::SaveFile()
{
    // 获取 xml
    QDomDocument doc = CCommonFunction::WriteComponentXmlFile(s_strFileName, MODEL_NAME, std::vector<QString>{COPY_FILE_INFO_TAG, UI_COPY_FILE_INFO_TAG});

    QDomElement root = doc.firstChildElement(MODEL_NAME);

    // 拷贝文件
    QDomElement copyFileInfo = doc.createElement(COPY_FILE_INFO_TAG);
    copyFileInfo.setAttribute(VERSION_ATTR, 1);
    root.appendChild(copyFileInfo);

    // 目标路径
    QDomElement elTargetPath = doc.createElement(TARGET_PATH_TAG);
    elTargetPath.setAttribute(PATH_ATRR_TAG, ui->leTargetPath->text());
    copyFileInfo.appendChild(elTargetPath);

    // 文件路径
    QDomElement elSrcPath = doc.createElement(SRC_PATH_TAG);
    elSrcPath.setAttribute(PATH_ATRR_TAG, ui->leSrcPath->text());
    elSrcPath.setAttribute(WATCHER_ATTR_TAG, ui->cbCopyFileWatch->checkState() == Qt::Checked ? 1 : 0);
    for (int i = 0; i < ui->copyFileWidget->getItemCount(); i++) {
        QListWidgetItem* item = ui->copyFileWidget->getItem(i);
        QDomElement elName = doc.createElement(NAME_TAG);
        elName.setAttribute(CHECKED_ATRR_TAG, item->checkState() == Qt::Checked ? "1" : "0");
        elName.appendChild(doc.createTextNode(item->text()));
        elSrcPath.appendChild(elName);
    }
    copyFileInfo.appendChild(elSrcPath);

    // ui 拷贝文件
    QDomElement copyUiFileInfo = doc.createElement(UI_COPY_FILE_INFO_TAG);
    copyUiFileInfo.setAttribute(VERSION_ATTR, 1);
    root.appendChild(copyUiFileInfo);

    // 目标路径
    QDomElement elUITargetPath = doc.createElement(TARGET_PATH_TAG);
    elUITargetPath.setAttribute(PATH_ATRR_TAG, ui->leUiTargetPath->text());
    copyUiFileInfo.appendChild(elUITargetPath);

    // 文件路径
    QDomElement elUiSrcPath = doc.createElement(SRC_PATH_TAG);
    elUiSrcPath.setAttribute(PATH_ATRR_TAG, ui->leUiSrcPath->text());
    elUiSrcPath.setAttribute(WATCHER_ATTR_TAG, ui->cbUiCopyFileWatch->checkState() == Qt::Checked ? 1 : 0);
    for (int i = 0; i < ui->uiCopyFileWidget->getItemCount(); i++) {
        QListWidgetItem* item = ui->uiCopyFileWidget->getItem(i);
        QDomElement elName = doc.createElement(NAME_TAG);
        elName.setAttribute(CHECKED_ATRR_TAG, item->checkState() == Qt::Checked ? "1" : "0");
        elName.appendChild(doc.createTextNode(item->text()));
        elUiSrcPath.appendChild(elName);
    }
    copyUiFileInfo.appendChild(elUiSrcPath);

    // zxp 路径
    QDomElement elZXPPath = doc.createElement(ZXP_PATH_TAG);
    elZXPPath.setAttribute(PATH_ATRR_TAG, ui->leZXPPath->text());
    copyUiFileInfo.appendChild(elZXPPath);

    // 证书
    QDomElement elCertificatePath = doc.createElement(CERTIFICATE_PATH_TAG);
    elCertificatePath.setAttribute(PATH_ATRR_TAG, ui->leCertificatePath->text());
    elCertificatePath.setAttribute(PASSWORD_TAG, ui->lePassword->text());
    copyUiFileInfo.appendChild(elCertificatePath);

    // 保存信息到文件
    CCommonFunction::SaveDomDocument(doc, s_strFileName);
}

void CCopyFileWidget::LoadFile()
{
    QFile file(s_strFileName);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        return;
    }

    QDomDocument doc;
    if (!doc.setContent(&file)) {
        return;
    }

    QDomElement root = doc.firstChildElement(MODEL_NAME);

    // 拷贝文件信息
    ui->leTargetPath->setText(root.firstChildElement(COPY_FILE_INFO_TAG).firstChildElement(TARGET_PATH_TAG).attribute(PATH_ATRR_TAG));
    QDomElement elCopyFileInfo = root.firstChildElement(COPY_FILE_INFO_TAG).firstChildElement(SRC_PATH_TAG);
    QDomNodeList list = elCopyFileInfo.childNodes();
    QString srcFilePath = elCopyFileInfo.attribute(PATH_ATRR_TAG);
    ui->cbCopyFileWatch->setCheckState(elCopyFileInfo.attribute(WATCHER_ATTR_TAG) == "1" ? Qt::Checked : Qt::Unchecked);
    QDir dir(srcFilePath);
    for (int i = 0; i < list.count(); i++) {
        QDomElement elName = list.at(i).toElement();

        // 拼接路径
        QString name = elName.firstChild().toText().nodeValue();
        QString newPath = dir.absoluteFilePath(name);
        QFile file(newPath);
        if (file.exists()) {
            ui->copyFileWidget->addListWidgetItem(nullptr, [=](void* pData, QString& showText, QString& tipText) { 
                showText =name; 
                tipText = newPath; }, (elName.attribute(CHECKED_ATRR_TAG).toInt() == 1) ? Qt::Checked : Qt::Unchecked);
        }
    }
    ui->leSrcPath->setText(srcFilePath);

    // ui拷贝文件信息
    QDomElement elUiCopyFile = root.firstChildElement(UI_COPY_FILE_INFO_TAG);
    ui->leUiTargetPath->setText(elUiCopyFile.firstChildElement(TARGET_PATH_TAG).attribute(PATH_ATRR_TAG));
    QDomElement elUiCopyFileInfo = root.firstChildElement(UI_COPY_FILE_INFO_TAG).firstChildElement(SRC_PATH_TAG);
    list = elUiCopyFileInfo.childNodes();
    QString srcUiFilePath = elUiCopyFileInfo.attribute(PATH_ATRR_TAG);
    ui->cbUiCopyFileWatch->setCheckState(elUiCopyFileInfo.attribute(WATCHER_ATTR_TAG) == "1" ? Qt::Checked : Qt::Unchecked);
    dir.setPath(srcUiFilePath);
    for (int i = 0; i < list.count(); i++) {
        QDomElement elName = list.at(i).toElement();

        // 拼接路径
        QString name = elName.firstChild().toText().nodeValue();
        QString newPath = dir.absoluteFilePath(name);
        QFile file(newPath);
        if (file.exists()) {
            ui->uiCopyFileWidget->addListWidgetItem(nullptr, [=](void* pData, QString& showText, QString& tipText) { 
                showText =name; 
                tipText = newPath; }, (elName.attribute(CHECKED_ATRR_TAG).toInt() == 1) ? Qt::Checked : Qt::Unchecked);
        }
    }
    ui->leUiSrcPath->setText(srcUiFilePath);

    // zxp 路径
    ui->leZXPPath->setText(elUiCopyFile.firstChildElement(ZXP_PATH_TAG).attribute(PATH_ATRR_TAG));
    ui->leCertificatePath->setText(elUiCopyFile.firstChildElement(CERTIFICATE_PATH_TAG).attribute(PATH_ATRR_TAG));
    ui->lePassword->setText(elUiCopyFile.firstChildElement(CERTIFICATE_PATH_TAG).attribute(PASSWORD_TAG));

    file.close();

    // 判断是否选中监听
    if (ui->cbCopyFileWatch->checkState() == Qt::Checked) {
        on_cbCopyFileWatch_clicked();
    }
    if (ui->cbUiCopyFileWatch->checkState() == Qt::Checked) {
        on_cbUiCopyFileWatch_clicked();
    }

    // 更新文件列表
    UpdateCopyFileSrcList(ui->leSrcPath->text());
    UpdateUiCopyFileSrcList(ui->leUiSrcPath->text());
}

void CCopyFileWidget::LoadSize(QWidget* parent)
{
    CMyWindow::LoadSizeFromFile(parent, s_strFileName);
}

void CCopyFileWidget::SaveSize(QWidget* parent)
{
    CMyWindow::SaveSizeToFile(parent, s_strFileName, MODEL_NAME);
}

QMenuBar* CCopyFileWidget::GetMenuBar()
{
    return nullptr;
}

int CCopyFileWidget::GetComponentId()
{
    return 1;
}

void CCopyFileWidget::on_tbTargetPath_clicked()
{
    QString path = QFileDialog::getExistingDirectory(this);
    if (!path.isEmpty()) {
        ui->leTargetPath->setText(path);
    }
}

void CCopyFileWidget::on_tbSrcPath_clicked()
{
    QString path = QFileDialog::getExistingDirectory(this);
    if (!path.isEmpty()) {
        ui->leSrcPath->setText(path);
    }
}

void CCopyFileWidget::on_tbUiTargetPath_clicked()
{
    QString path = QFileDialog::getExistingDirectory(this);
    if (!path.isEmpty()) {
        ui->leUiTargetPath->setText(path);
        UpdateCopyFileSrcList(path);
    }
}

void CCopyFileWidget::on_tbUiSrcPath_clicked()
{
    QString path = QFileDialog::getExistingDirectory(this);
    if (!path.isEmpty()) {
        ui->leUiSrcPath->setText(path);
        UpdateUiCopyFileSrcList(path);
    }
}

void CCopyFileWidget::UpdateCopyFileSrcList(const QString& path)
{
    // 存储已选中的文件名
    QStringList selectedFiles;
    auto vCheckedItem = ui->copyFileWidget->getCheckedItem();
    for (auto item : vCheckedItem) {
        selectedFiles << item->text();
    }

    // 清空列表
    ui->copyFileWidget->clearItems();

    QDir dir(path);
    if (dir.exists()) {
        dir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
        QFileInfoList list = dir.entryInfoList();
        for (const QFileInfo& fileInfo : list) {
            QString fileName = fileInfo.fileName();

            auto pFun = [=](void* pData, QString& showText, QString& tipText) {
                showText = fileName;
                tipText = fileInfo.absoluteFilePath();
            };
            ui->copyFileWidget->addListWidgetItem(nullptr, pFun, selectedFiles.indexOf(fileName) == -1 ? Qt::Unchecked : Qt::Checked);
        }
    }
}

void CCopyFileWidget::UpdateUiCopyFileSrcList(const QString& path)
{
    // 存储已选中的文件名
    QStringList selectedFiles;
    auto vCheckedItem = ui->uiCopyFileWidget->getCheckedItem();
    for (auto item : vCheckedItem) {
        selectedFiles << item->text();
    }

    // 清空列表
    ui->uiCopyFileWidget->clearItems();

    QDir dir(path);
    if (dir.exists()) {
        dir.setFilter(QDir::Dirs);
        QFileInfoList list = dir.entryInfoList();
        for (const QFileInfo& fileInfo : list) {
            QString fileName = fileInfo.fileName();
            if (fileName == "." || fileName == "..") {
                continue;
            }

            auto pFun = [=](void* pData, QString& showText, QString& tipText) {
                showText = fileName;
                tipText = fileInfo.absoluteFilePath();
            };
            ui->uiCopyFileWidget->addListWidgetItem(nullptr, pFun, selectedFiles.indexOf(fileName) == -1 ? Qt::Unchecked : Qt::Checked);
        }
    }
}

void CCopyFileWidget::ShowInfo(const QString& str, EnumInfoType type)
{
    QTime dateTime = QTime::currentTime();
    QString text = dateTime.toString("hh:mm:ss") + " " + str;
    CComponentBridge* pBridget = CComponentBridge::GetInstance();

    switch (type) {
        case EnumInfoType::eSuccess:
            ui->plainTextEdit->appendHtml("<font color='green'>" + text + "</font>");
            pBridget->ShowSystemMessage(STR_TITLE, text, QSystemTrayIcon::Information);
            break;

        case EnumInfoType::eWarning:
            ui->plainTextEdit->appendHtml("<font color='red'>" + text + "</font>");
            break;

        case EnumInfoType::eError:
            ui->plainTextEdit->appendHtml("<font color='red'>" + text + "</font>");
            pBridget->ShowSystemMessage(STR_TITLE, text, QSystemTrayIcon::Critical);
            break;

        case EnumInfoType::eInfo:
            ui->plainTextEdit->appendHtml("<font color='black'>" + text + "</font>");
            break;

        case EnumInfoType::eText:
            ui->plainTextEdit->appendHtml("<font color='black'>" + str + "</font>");
            break;

        default:
            break;
    }
}

void CCopyFileWidget::on_btnExecCopyFile_clicked()
{
    // 判断目标目录是否存在
    QDir targetDir(ui->leTargetPath->text());
    QDir srcDir(ui->leSrcPath->text());
    if (!targetDir.exists()) {
        if (!targetDir.mkdir(ui->leTargetPath->text())) {
            ShowInfo("目标目录创建失败！", EnumInfoType::eError);
            return;
        }
        else {
            ShowInfo("目标目录不存在，已创建！", EnumInfoType::eWarning);
        }
    }

    // 获取每一个勾选的内容
    auto list = ui->copyFileWidget->getCheckedItem();
    for (int i = 0; i < list.size(); ++i) {
        QString fileName = list.at(i)->text();
        QString targetFilePath = targetDir.absoluteFilePath(fileName);
        QFile file(targetFilePath);

        // 目标路径中存在，则删除
        bool bExist = false;
        if (file.exists()) {
            if (!file.remove()) {
                ShowInfo("目标文件 " + fileName + " 已存在，删除失败！", EnumInfoType::eError);
                continue;
            }
            bExist = true;
        }

        // 复制文件
        if (QFile::copy(srcDir.absoluteFilePath(fileName), targetFilePath)) {
            if (bExist) {
                ShowInfo("目标文件 " + fileName + " 已存在，覆盖成功！", EnumInfoType::eSuccess);
            }
            else {
                ShowInfo("目标文件 " + fileName + " 复制成功！", EnumInfoType::eSuccess);
            }
        }
        else {
            ShowInfo("目标文件 " + fileName + " 文件拷贝失败！", EnumInfoType::eError);
        }
    }
}

void CCopyFileWidget::on_copyFileWidget_itemClicked(QListWidgetItem* item)
{
    QDir dir(ui->leSrcPath->text());
    QString fileName = dir.absoluteFilePath(item->text());
    if (item->checkState() == Qt::Checked) {
        m_copyFileSystem.addWatcherPath(fileName);
    }
    else {
        m_copyFileSystem.removeWatcherPath(fileName);
    }
}

void CCopyFileWidget::on_btnRefreshCopyFileSrc_clicked()
{
    UpdateCopyFileSrcList(ui->leSrcPath->text());
}

void CCopyFileWidget::slotCopyFileChanged(const QString& path)
{
    QFileInfo fileInfo(path);

    // 判断监听文件是否存在
    if (!fileInfo.exists()) {
        ShowInfo("监听文件 " + fileInfo.fileName() + " 已删除！", EnumInfoType::eWarning);
        return;
    }

    QDir targetDir(ui->leTargetPath->text());
    QString targetFilePath = targetDir.absoluteFilePath(fileInfo.fileName());
    QFile file(targetFilePath);
    bool bExist = false;
    if (file.exists()) {
        bExist = true;

        // 删除文件
        if (!file.remove()) {
            ShowInfo("监听到 " + fileInfo.fileName() + " 改变，但删除失败！", EnumInfoType::eError);
            return;
        }
    }

    // 拷贝
    if (QFile::copy(path, targetFilePath)) {
        if (bExist) {
            ShowInfo("监听到 " + fileInfo.fileName() + " 改变，并成功覆盖！", EnumInfoType::eSuccess);
        }
        else {
            ShowInfo("监听到 " + fileInfo.fileName() + " 改变，并成功拷贝！", EnumInfoType::eSuccess);
        }
    }
    else {
        ShowInfo("监听到 " + fileInfo.fileName() + " 改变，但拷贝失败！", EnumInfoType::eError);
    }
}

void CCopyFileWidget::slotCopyFileDirectoryChanged(const QString& path)
{
    Q_UNUSED(path)
    QDir dir(ui->leSrcPath->text());
    auto vItems = ui->copyFileWidget->getCheckedItem();
    for (auto item : vItems) {
        bool b = m_copyFileSystem.addWatcherPath(dir.absoluteFilePath(item->text()));
        if (b) {
            ShowInfo("找到 " + item->text() + " 并重新监听！", EnumInfoType::eWarning);
        }
    }
}

void CCopyFileWidget::slotUiCopyFileChanged(const QString& path)
{
    QFile file(path);
    QString fileName = path.mid(ui->leUiSrcPath->text().size() + 1);
    if (!file.exists()) {
        ShowInfo("监听文件 " + fileName + " 已删除！", EnumInfoType::eWarning);
    }

    // 获取对应的ui模块名
    QString uiName = fileName.split("/").at(0);
    QDir dir(ui->leUiSrcPath->text());
    ShowInfo("重新生成 " + uiName + " 项目！", EnumInfoType::eInfo);
    ExecutUI(uiName);
}

void CCopyFileWidget::slotUiCopyFileDirectoryChanged(const QString& path)
{
    ShowInfo("监听到 " + path.mid(ui->leUiSrcPath->text().size() + 1) + " 文件夹改变！", EnumInfoType::eWarning);
    QStringList list;
    GetAllFileDirector(path, list);
    for (int i = 0; i < list.size(); ++i) {
        QFileInfo fileInfo(list.at(i));
        if (fileInfo.isFile()) {
            if (m_uiCopyFileSystem.addWatcherPath(fileInfo.absoluteFilePath())) {
                ShowInfo("增加 " + fileInfo.fileName() + " 文件监听！", EnumInfoType::eWarning);
            }
        }
        else if (fileInfo.isDir()) {
            if (m_uiCopyFileSystem.addWatcherPath(fileInfo.absoluteFilePath())) {
                ShowInfo("增加 " + fileInfo.fileName() + " 文件夹监听！", EnumInfoType::eWarning);
            }
        }
    }

    // 获取对应的ui模块名
    //    QString uiName = path.mid(ui->leUiSrcPath->text().size() + 1).split("/").at(0);
    //    QDir dir(ui->leUiSrcPath->text());
    //    ShowInfo("重新生成 " + uiName + " 项目！", EnumInfoType::eInfo);
    //    ExecutUI(uiName);
}

void CCopyFileWidget::on_cbCopyFileWatch_clicked()
{
    if (ui->cbCopyFileWatch->checkState() == Qt::Checked) {
        ui->leTargetPath->setEnabled(false);
        ui->leSrcPath->setEnabled(false);
        ui->tbTargetPath->setEnabled(false);
        ui->tbSrcPath->setEnabled(false);
        ui->btnRefreshCopyFileSrc->setEnabled(false);
        // ui->btnExecCopyFile->setEnabled(false);
        ui->copyFileWidget->setEnabled(false);

        // 为每个选中的文件增减监听器
        ShowInfo("********** 已开始监听文件变化！ **********", EnumInfoType::eText);
        QDir dir(ui->leSrcPath->text());
        auto vItems = ui->copyFileWidget->getCheckedItem();
        for (auto item : vItems) {
            m_copyFileSystem.addWatcherPath(dir.absoluteFilePath(item->text()));
            ShowInfo("开始监听 " + item->text(), EnumInfoType::eInfo);
        }
        m_copyFileSystem.addWatcherPath(ui->leSrcPath->text());
        ShowInfo("****************************************", EnumInfoType::eText);
    }
    else {
        ui->leTargetPath->setEnabled(true);
        ui->leSrcPath->setEnabled(true);
        ui->tbTargetPath->setEnabled(true);
        ui->tbSrcPath->setEnabled(true);
        ui->btnRefreshCopyFileSrc->setEnabled(true);
        // ui->btnExecCopyFile->setEnabled(true);
        ui->copyFileWidget->setEnabled(true);

        // 去除所有的监听器
        m_copyFileSystem.removeWatcherPaths(m_copyFileSystem.GetDirectoriesWather());
        m_copyFileSystem.removeWatcherPaths(m_copyFileSystem.GetFilesWather());
        ShowInfo("****************************************", EnumInfoType::eText);
        ShowInfo("已关闭文件监听变化！", EnumInfoType::eInfo);
        ShowInfo("****************************************", EnumInfoType::eText);
    }
}

void CCopyFileWidget::on_btnClearInfo_clicked()
{
    ui->plainTextEdit->clear();
}

// 递归函数，用于获取目录中的所有文件及文件夹路径
void CCopyFileWidget::GetAllFileDirector(const QDir& dir, QStringList& fileList)
{
    QFileInfoList entries = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);

    for (const QFileInfo& entry : entries) {
        // 文件及文件夹都添加
        fileList << entry.absoluteFilePath();

        if (entry.isDir()) {
            // 如果是目录，则递归调用 GetAllFileDirector
            QDir subDir(entry.absoluteFilePath());
            GetAllFileDirector(subDir, fileList);
        }
    }
}

void CCopyFileWidget::ExecutUI(const QString& fileName)
{
    QDir dirSrc(ui->leUiSrcPath->text());
    QDir dirTarget(ui->leUiTargetPath->text());
    QProcess process;

    QString srcZXPFileName = dirSrc.absoluteFilePath(fileName) + ".zxp";
    QFile file(srcZXPFileName);
    if (file.exists()) {
        if (!file.remove()) {
            ShowInfo("已存在 " + fileName + ".zxp 文件，但删除失败，后续操作中断执行！", EnumInfoType::eError);
            return;
        }
        else {
            ShowInfo("已存在 " + fileName + ".zxp 文件，已删除！", EnumInfoType::eSuccess);
        }
    }

    QStringList arguments;
    arguments << "-sign";
    arguments << dirSrc.absoluteFilePath(fileName);
    arguments << srcZXPFileName;
    arguments << ui->leCertificatePath->text();
    arguments << ui->lePassword->text();
    // qDebug() << arguments;
    process.start(ui->leZXPPath->text(), arguments);

    // 等待进程完成
    if (process.waitForFinished(-1)) {
        if (process.exitCode() == 0) {
            // ShowInfo(fileName + ".zxp 生成成功！", EnumInfoType::eSuccess);
        }
        else {
            ShowInfo(fileName + ".zxp 生成失败！", EnumInfoType::eError);
            ShowInfo(process.readAllStandardError(), EnumInfoType::eError);
            return;
        }
    }
    else {
        ShowInfo("生成超时，" + fileName + ".zxp 生成失败！", EnumInfoType::eError);
        ShowInfo(process.errorString(), EnumInfoType::eError);
        return;
    }

    // 判断目标目录是否存在
    QDir newDir = dirTarget.absoluteFilePath(fileName);
    bool b = false;
    if (newDir.exists()) {
        if (newDir.removeRecursively()) {
            b = true;
        }
        else {
            ShowInfo("目标文件夹下 " + fileName + " 文件夹删除失败！", EnumInfoType::eError);
            return;
        }
    }

    // 创建目标文件夹
    newDir.mkdir(fileName);

    // 解压
    QZipReader zipReader(arguments.at(2));
    if (zipReader.extractAll(newDir.absolutePath())) {
        if (b) {
            ShowInfo("目标目录 " + fileName + " 已存在，并替换！", EnumInfoType::eSuccess);
        }
        else {
            ShowInfo(fileName + " 已成功生成！", EnumInfoType::eSuccess);
        }
        zipReader.close();
    }
    else {
        ShowInfo(fileName + ".zxp 解压失败！", EnumInfoType::eError);
        zipReader.close();
        return;
    }

    // 删除生成 exp 文件
    if (!QFile::remove(arguments.at(2))) {
        ShowInfo(fileName + ".zxp 删除失败！", EnumInfoType::eError);
    }
}

void CCopyFileWidget::on_cbUiCopyFileWatch_clicked()
{
    if (ui->cbUiCopyFileWatch->checkState() == Qt::Checked) {
        ui->leUiTargetPath->setEnabled(false);
        ui->leUiSrcPath->setEnabled(false);
        ui->leCertificatePath->setEnabled(false);
        ui->lePassword->setEnabled(false);
        ui->leZXPPath->setEnabled(false);

        ui->tbUiTargetPath->setEnabled(false);
        ui->tbUiSrcPath->setEnabled(false);
        ui->tbCertificateSelect->setEnabled(false);
        ui->tbZXPSelect->setEnabled(false);

        ui->btnRefreshUiCopyFileSrc->setEnabled(false);
        ui->uiCopyFileWidget->setEnabled(false);

        // 添加监听器
        ShowInfo("********** 已开始监听文件变化！ **********", EnumInfoType::eText);
        QDir dir(ui->leUiSrcPath->text());
        auto vItems = ui->uiCopyFileWidget->getCheckedItem();
        for (auto item : vItems) {
            ShowInfo("开始监听文件夹 " + item->text(), EnumInfoType::eInfo);

            // 监听文件夹
            m_uiCopyFileSystem.addWatcherPath(dir.absoluteFilePath(item->text()));

            // 监听文件
            QStringList fileList;
            GetAllFileDirector(dir.absoluteFilePath(item->text()), fileList);
            for (int i = 0; i < fileList.size(); ++i) {
                QString str = fileList.at(i);
                QFileInfo fileInfo(str);
                if (fileInfo.isFile()) {
                    ShowInfo("开始监听文件 " + str.mid(dir.absoluteFilePath(item->text()).size() + 1), EnumInfoType::eInfo);
                }
                else if (fileInfo.isDir()) {
                    ShowInfo("开始监听文件夹 " + str.mid(dir.absoluteFilePath(item->text()).size() + 1), EnumInfoType::eInfo);
                }
                m_uiCopyFileSystem.addWatcherPath(str);
            }
        }
        ShowInfo("****************************************", EnumInfoType::eText);
    }
    else {
        ui->leUiTargetPath->setEnabled(true);
        ui->leUiSrcPath->setEnabled(true);
        ui->leCertificatePath->setEnabled(true);
        ui->lePassword->setEnabled(true);
        ui->leZXPPath->setEnabled(true);

        ui->tbUiTargetPath->setEnabled(true);
        ui->tbUiSrcPath->setEnabled(true);
        ui->tbCertificateSelect->setEnabled(true);
        ui->tbZXPSelect->setEnabled(true);

        ui->btnRefreshUiCopyFileSrc->setEnabled(true);
        ui->uiCopyFileWidget->setEnabled(true);

        // 去除所有的监听器
        m_copyFileSystem.removeWatcherPaths(m_copyFileSystem.GetDirectoriesWather());
        m_copyFileSystem.removeWatcherPaths(m_copyFileSystem.GetFilesWather());
        ShowInfo("****************************************", EnumInfoType::eText);
        ShowInfo("已关闭文件监听变化！", EnumInfoType::eInfo);
        ShowInfo("****************************************", EnumInfoType::eText);
    }
}

void CCopyFileWidget::on_tbZXPSelect_clicked()
{
    QString path = QFileDialog::getOpenFileName(this, "选择 zxp 工具", QString(), "Execute Files (*.exe)");
    if (!path.isEmpty()) {
        ui->leZXPPath->setText(path);
    }
}

void CCopyFileWidget::on_tbCertificateSelect_clicked()
{
    QString path = QFileDialog::getOpenFileName(this, "选择证书");
    if (!path.isEmpty()) {
        ui->leCertificatePath->setText(path);
    }
}

void CCopyFileWidget::on_btnRefreshUiCopyFileSrc_clicked()
{
    UpdateUiCopyFileSrcList(ui->leUiSrcPath->text());
}

void CCopyFileWidget::on_btnExecUiCopyFile_clicked()
{
    auto checkItem = ui->uiCopyFileWidget->getCheckedItem();
    for (int i = 0; i < checkItem.size(); ++i) {
        ExecutUI(checkItem.at(i)->text());
    }
}
